package com.tc.utils.image.tree;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * Created by Frederic.Tang on 2018/8/22.
 */
public class RectNode {
    private String text;
    private int x, y;
    private int w, h;
    private int pad;
    private int fw, fh;
    private int fontSize;
    private int margin;
    private int marginx = 60;
    private int th, tw;
    private int border = 3;
    private RectNode parent = null;
    private List<RectNode> children = new ArrayList<>();
    private Color rectColor;
    private Color fontColor;
    private Color borderColor;
    private static List<Color> borderColorPool = Arrays.asList(
            new Color(171, 94, 96),
            new Color(172, 174, 96),
            new Color(99, 175, 96),
            new Color(99, 173, 172),
            new Color(102, 139, 139),
            new Color(220, 20, 60),
            new Color(199, 21, 133),
            new Color(218, 112, 214),
            new Color(255, 0, 255),
            new Color(128, 0, 128),
            new Color(147, 112, 219),
            new Color(106, 90, 205),
            new Color(0, 0, 255),
            new Color(65, 105, 225),
            new Color(100, 149, 237),
            new Color(95, 158, 160),
            new Color(0, 128, 128),
            new Color(32, 178, 170),
            new Color(46, 139, 87),
            new Color(107, 142, 35),
            new Color(189, 183, 107),
            new Color(218, 165, 32),
            new Color(255, 165, 0),
            new Color(205, 133, 63),
            new Color(244, 164, 96),
            new Color(210, 105, 30),
            new Color(160, 82, 45),
            new Color(255, 127, 80),
            new Color(255, 99, 71),
            new Color(165, 42, 42),
            new Color(128, 0, 0),
            new Color(105, 105, 105),
            new Color(105, 205, 105),
            new Color(205, 105, 105)

    );
    private static Random random = new Random();

    public RectNode(String text) {
        this.setText(text);
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public List<RectNode> getChildren() {
        return children;
    }

    public void setChildren(List<RectNode> children) {
        this.children = children;
    }

    public RectNode attach(RectNode parent) {

        parent.children.add(this);
        this.parent = parent;
        return parent;
    }

    /**
     * 返回父节点
     */
    public RectNode addChild(RectNode child) {
        this.children.add(child);
        child.parent = this;
        return this;
    }

    /**
     * 返回父节点
     */
    public RectNode addChild(String text) {
        RectNode child = new RectNode(text);
        this.children.add(child);
        child.parent = this;
        return this;
    }

    /**
     * 返回子节点
     */
    public RectNode createChild(String text) {
        RectNode child = new RectNode(text);
        this.children.add(child);
        child.parent = this;
        return child;
    }

    public RectNode getParent() {
        return parent;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getW() {
        return w;
    }

    public void setW(int w) {
        this.w = w;
    }

    public int getH() {
        return h;
    }

    public void setH(int h) {
        this.h = h;
    }

    private void draw(Graphics2D g) {

        Font font = new Font("黑体", Font.PLAIN, fontSize);
        g.setFont(font);


        g.setColor(borderColor);
        g.fillRect(x, y, w, h);
        g.setColor(rectColor);
        g.fillRect(x + border, y + border, w - 2 * border, h - 2 * border);

        g.setColor(fontColor);
        g.drawString(text, x + pad, y + fh * 8 / 10 + pad);


        for (RectNode c : children) {
            c.draw(g);
            g.setColor(c.borderColor);
            BasicStroke bs1 = new BasicStroke(border);
            g.setStroke(bs1);
            g.drawArc(x + w / 2, 2 * y + 2 * h - c.y - c.h / 2, marginx * 2 - 16, 2 * (c.y + c.h / 2 - y - h), 180, 90);
            drawArrow(g, c.x, c.y + c.h / 2);

        }

    }

    private void drawArrow(Graphics2D g, int x, int y) {
        int px1[] = {x + 0, x - 8, x - 8};
        int py1[] = {y + 0, y + 5, y - 5};
        g.fillPolygon(px1, py1, 3);
    }

    private void calc(Graphics2D g) {

        if (parent == null) {
            margin = 20;
            setX(marginx);
            setY(margin);
            pad = 20;
            fontSize = 25;
            rectColor = new Color(206, 255, 103);
            fontColor = new Color(76, 76, 76);
            borderColor = new Color(128, 128, 128);
        } else {
            pad = 10;
            fontSize = 20;
            margin = 5;
            setX(parent.x + parent.w / 2 + marginx);
            setY(parent.y + parent.th + margin);
            rectColor = new Color(255, 255, 255);
            fontColor = new Color(48, 48, 48);
            borderColor = borderColorPool.get(random.nextInt(borderColorPool.size()));

        }
        Font font = new Font("黑体", Font.PLAIN, fontSize);
        g.setFont(font);


        FontMetrics fm = g.getFontMetrics();
        Rectangle2D size = fm.getStringBounds(text, g);
        fw = (int) size.getWidth();
        fh = (int) size.getHeight();
        w = fw + 2 * pad;
        h = fh + 2 * pad;
        System.out.println(text + ",(" + x + "," + y + ")(" + w + "," + h + ")");
        th = h + margin;
        tw = x + w + marginx;
        //tw=parent==null?tw:parent.x+parent.w/2+tw;
        if (children.size() > 0) {
            th += children.get(0).margin;
        }
        for (RectNode c : children) {
            c.calc(g);
            th += c.th + c.margin;
            if (c.tw > tw) {
                tw = c.tw;
            }
        }


    }

    public int getFh() {
        return fh;
    }

    public int getTw() {
        return tw;
    }

    public void setFh(int fh) {
        this.fh = fh;
    }

    public int getTh() {
        return th;
    }

    public void setTh(int th) {
        this.th = th;
    }

    public int getMargin() {
        return margin;
    }


    public void write(String file) throws IOException {

        RectNode root = this;
        BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        //drawAll();


        root.calc(g);
        int height = root.getTh() + 2 * root.getMargin();
        int width = root.getTw();
        //image.flush();
        g.dispose();
        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);


        GradientPaint paint = new GradientPaint(10, 10, new Color(237, 238, 241), 10, 15, new Color(241, 242, 244), true);
        g.setPaint(paint);

        g.fillRect(0, 0, width, height);


        root.draw(g);
        g.dispose();
        OutputStream os = new FileOutputStream(file);
        ImageIO.write(image, "JPEG", os);
    }
}
